/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = rtsp_packet.c                                      */
/*  NOTE      =                                                    */
/*  DATE      = 2015/07/14 by songbb                               */
/*******************************************************************/

#include "frct_comm.h"

#include "rtsp_comm.h"
#include "rtsp_core.h"
#include "rtsp_packet.h"
#include "rtsp_header.h"

/*******************************************************************************
*  FUNC     :  初始化RTSP包的信息
*  ARGS     :  *p_st_rtsp_packet                     (RTSP数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int rtsp_init_packet(L7_rtsp_packet *p_st_rtsp_packet)
{
    RTSP_PRINT_INFO("init rtsp_packet...\n");
    if (p_st_rtsp_packet == NULL)
        return FR_SUCC;

    bytebuff_free(&(p_st_rtsp_packet->p_st_packet));
    rtsp_free((void **) &(p_st_rtsp_packet->p_req_method));
    p_st_rtsp_packet->i_is_rtsp_req = APM_RTSP_FLAG_UNSET;
    p_st_rtsp_packet->ui_length = 0;
    p_st_rtsp_packet->ui_content_length = 0;
    p_st_rtsp_packet->em_req_method = RTSP_METHOD_TYPE_UNKNOWN;
    if ((p_st_rtsp_packet->p_st_packet = bytebuff_creat()) == NULL)
        return FR_FAIL;
    p_st_rtsp_packet->fragment_state = APM_RTSP_FRAGMENT_INIT;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  检查数据是否是分片包
*  ARGS     :  *p_st_rtsp_packet                    (RTSP数据包)
*           :  *p_data                              (数据内容)
*           :  ui_len                               (数据长度)
*  RTN      :  0                                    (是分片包)
*              1                                    (不是分片包)
*              2                                    (出错)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __rtsp_pkt_is_fragmented(L7_rtsp_packet *p_st_rtsp_packet
                                        , char *p_data
                                        , unsigned int ui_len)
{
    unsigned int ui_header_len = 0;
    int i_content_len = 0;
    char *p_pos = NULL;
    int i_is_rtsp_req;

    if ((p_pos = strstr(p_data, APM_RTSP_EOH)) == NULL)
        goto fragmented;

    ui_header_len = p_pos - p_data + strlen(APM_RTSP_EOH);

    rtsp_free((void **) &(p_st_rtsp_packet->p_req_method));
    if (ui_header_len == ui_len)
    {
        if (rtsp_analyze_header(p_data, ui_len, &i_is_rtsp_req, &(p_st_rtsp_packet->p_req_method), &(p_st_rtsp_packet->em_req_method), NULL) != FR_SUCC)
            goto error;
        p_st_rtsp_packet->i_is_rtsp_req = i_is_rtsp_req;
        p_st_rtsp_packet->ui_length = ui_header_len;
        goto not_fragmented;
    }

    if (rtsp_analyze_header(p_data, ui_len, &i_is_rtsp_req, &(p_st_rtsp_packet->p_req_method), &(p_st_rtsp_packet->em_req_method), &i_content_len) != FR_SUCC)
        goto error;

    RTSP_PRINT_DBG("ui_header_len:[%d] i_content_len:[%d] total_len:[%d]\n", ui_header_len, i_content_len, ui_header_len + i_content_len);

    p_st_rtsp_packet->ui_length = ui_header_len + i_content_len;
    p_st_rtsp_packet->ui_content_length = (unsigned int) i_content_len;
    p_st_rtsp_packet->i_is_rtsp_req = i_is_rtsp_req;
    if (ui_len < ui_header_len + i_content_len)
    {
        RTSP_PRINT_INFO("__rtsp_pkt_is_fragmented ui_len:[%d] ui_header_len:[%d] i_content_len:[%d]\n", ui_len, ui_header_len, i_content_len);
        goto fragmented;
    }
    else if (ui_len > ui_header_len + i_content_len)
        goto error;
    else
        goto not_fragmented;

fragmented:
    return APM_RTSP_PACKET_FRAGMENTED;
not_fragmented:
    return APM_RTSP_PACKET_UNFRAGMENTED;
error:
    return APM_RTSP_PACKET_ERROR;
}

/*******************************************************************************
*  FUNC     :  检查分片包信息
*  ARGS     :  i_is_request                         (是否是请求)
*           :  *p_payload                           (数据内容)
*           :  ui_payload_len                       (数据长度)
*           :  st_timestamp_first                   (分片包时，第一个分片包的时间；不为分片包时与st_timestamp_last相同)
*           :  *p_st_rtsp_packet                    (RTSP数据包)
*  RTN      :  0                                    (是分片包)
*              1                                    (不是分片包)
*              2                                    (出错)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __rtsp_packet_check_fragment(int i_is_request
                                            , char *p_payload
                                            , unsigned int ui_payload_len
                                            , struct timeval st_timestamp
                                            , L7_rtsp_packet *p_st_rtsp_packet)
{
    int i_is_fragmented = 0;

    i_is_fragmented = __rtsp_pkt_is_fragmented(p_st_rtsp_packet, p_payload, ui_payload_len);
    if (i_is_fragmented == APM_RTSP_PACKET_FRAGMENTED) // 是分片包
    {
        p_st_rtsp_packet->st_timestamp_first = st_timestamp;
        RTSP_PRINT_NOTICE("bytebuff_add first fragmented packet\n");
        if (bytebuff_add(p_st_rtsp_packet->p_st_packet, p_payload, ui_payload_len) != FR_SUCC)
            goto error;
        p_st_rtsp_packet->fragment_state = i_is_request ? APM_RTSP_FRAGMENT_NEED_NEXT_REQ_PACKET : APM_RTSP_FRAGMENT_NEED_NEXT_RESP_PACKET;
        goto need_next_packet;
    }
    else if (i_is_fragmented == APM_RTSP_PACKET_UNFRAGMENTED) // 不是分片包
    {
        RTSP_PRINT_NOTICE("bytebuff_add unfragmented packet\n");
        if (bytebuff_add(p_st_rtsp_packet->p_st_packet, p_payload, ui_payload_len) != FR_SUCC)
            goto error;
        p_st_rtsp_packet->st_timestamp_first = st_timestamp;
        p_st_rtsp_packet->st_timestamp_last = st_timestamp;
        p_st_rtsp_packet->fragment_state = APM_RTSP_FRAGMENT_INIT;
    }
    else
        goto error;

    return APM_RTSP_CHECK_FRAGMENT_SUCCESS;
need_next_packet:
    RTSP_PRINT_WARN("NEED NEXT PACKET!\n");
    return APM_RTSP_CHECK_FRAGMENT_NEED_NEXT_PACKET;
error:
    bytebuff_free(&(p_st_rtsp_packet->p_st_packet));
    return APM_RTSP_CHECK_FRAGMENT_ERROR;
}

/*******************************************************************************
*  FUNC     :  预备需要解析的数据
*  ARGS     :  *p_st_sess                           (RTSP私有的session)
*           :  *p_st_packet                        (协议分析入力数据)
*           :  *p_st_rtsp_packet                     (RTSP数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int rtsp_packet_unfragment(L7session_rtsp *p_st_sess
                        , Apm_packet *p_st_packet
                        , L7_rtsp_packet *p_st_rtsp_packet)
{
    char *p_payload = NULL;
    unsigned int ui_payload_len = 0;
    int i_fun_ret;

    if (p_st_packet->i_direction == FR_DIRECT_UNKNOWN)
        goto error;

    p_payload = p_st_packet->p_payload;
    ui_payload_len = p_st_packet->ui_payload_len;

    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV) // 请求包
    {
        if (p_st_rtsp_packet->fragment_state == APM_RTSP_FRAGMENT_NEED_NEXT_RESP_PACKET)
        {
            rtsp_core_add_unfinshed_fragmented_packets(p_st_sess);
            RTSP_PRINT_EMERG("detect unfinshed response fragmented packet\n");
            RTSP_PRINT_PACKET("unfinshed error packet", p_st_rtsp_packet);
            if (rtsp_init_packet(p_st_rtsp_packet) != FR_SUCC)
                goto error;
        }
        if (p_st_rtsp_packet->fragment_state == APM_RTSP_FRAGMENT_NEED_NEXT_REQ_PACKET)
        {
            RTSP_PRINT_NOTICE("bytebuff_add next packet\n");
            if (bytebuff_add(p_st_rtsp_packet->p_st_packet
                    , p_st_packet->p_payload
                    , p_st_packet->ui_payload_len) != FR_SUCC)
                goto error;
            p_st_rtsp_packet->st_timestamp_last = p_st_packet->st_timestamp;
        }
        else
        {
            if (rtsp_init_packet(p_st_rtsp_packet) != FR_SUCC)
                goto error;
        }

        i_fun_ret = __rtsp_packet_check_fragment(FR_YES, p_payload, ui_payload_len, p_st_packet->st_timestamp, p_st_rtsp_packet);
        return i_fun_ret;
    }
    else if (p_st_packet->i_direction == FR_DIRECT_SRV2CLIENT) // 响应包
    {
        if (p_st_rtsp_packet->fragment_state == APM_RTSP_FRAGMENT_NEED_NEXT_REQ_PACKET)
        {
            rtsp_core_add_unfinshed_fragmented_packets(p_st_sess);
            RTSP_PRINT_EMERG("detect unfinshed request fragmented packet\n");
            RTSP_PRINT_PACKET("unfinshed error packet", p_st_rtsp_packet);
            if (rtsp_init_packet(p_st_rtsp_packet) != FR_SUCC)
                goto error;
        }
        if (p_st_rtsp_packet->fragment_state == APM_RTSP_FRAGMENT_NEED_NEXT_RESP_PACKET)
        {
            RTSP_PRINT_NOTICE("bytebuff_add next packet\n");
            if (bytebuff_add(p_st_rtsp_packet->p_st_packet
                    , p_st_packet->p_payload
                    , p_st_packet->ui_payload_len) != FR_SUCC)
                goto error;
            p_st_rtsp_packet->st_timestamp_last = p_st_packet->st_timestamp;
        }
        else
        {
            if (rtsp_init_packet(p_st_rtsp_packet) != FR_SUCC)
                goto error;
        }

        i_fun_ret = __rtsp_packet_check_fragment(FR_NO, p_payload, ui_payload_len, p_st_packet->st_timestamp, p_st_rtsp_packet);
        return i_fun_ret;
    }

error:
    return APM_RTSP_CHECK_FRAGMENT_ERROR;
}
